package org.dydl.common.config;

import java.util.Date;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.dydl.common.util.DateUtil;
import org.dydl.common.util.WebUtil;
import org.dydl.model.system.SysLog;
import org.dydl.service.system.ISysLogService;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.web.DefaultErrorAttributes;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.NamedThreadLocal;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.alibaba.fastjson.JSON;

@Configuration
public class LogHandlerInterceptor extends HandlerInterceptorAdapter {

	protected final Log logger = LogFactory.getLog(getClass());
	private final ThreadLocal<Long> startTimeThreadLocal = new NamedThreadLocal<Long>("ThreadLocal StartTime");

	@Autowired
	private ISysLogService sysLogService;

	public void setSysLogService(ISysLogService sysLogService) {
		this.sysLogService = sysLogService;
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// logger.info("LogHandlerInterceptor ===========" +
		// request.getRequestURL().toString() +
		// request.getContextPath().toString());
		return true;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {

		startTimeThreadLocal.set(System.currentTimeMillis());

		// logger.info("LogHandlerInterceptor ===========" +
		// response.getStatus());
		/*
		 * if(response.getStatus()==500){ modelAndView.setViewName("/errorpage/500");
		 * }else if(response.getStatus()==404){
		 * modelAndView.setViewName("/errorpage/404"); }
		 */

		super.postHandle(request, response, handler, modelAndView);
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {

		try {
			if (handler instanceof HandlerMethod) {

				HandlerMethod handlerMethod = (HandlerMethod) handler;

				SysLog dblog = new SysLog();
				/**
				 * 获取跳转之前的请求路径 得到map如：{timestamp=Thu Oct 20 13:15:57 CST 2016, status=401,
				 * error=Unauthorized, message=Token验证失败！, path=/api/users/list}
				 */
				Map<String, Object> errorInfo = new DefaultErrorAttributes()
						.getErrorAttributes(new ServletRequestAttributes(request), true);

				try {
					dblog.setUrl(request.getRequestURL().toString() + " (" + errorInfo.get("path").toString() + ")");
					logger.info(request.getRequestURL().toString() + " (原始请求：" + errorInfo.get("path").toString() + ")"
							+ " status:" + errorInfo.get("status") + " error:" + errorInfo.get("error"));
				} catch (Exception e) {
					dblog.setUrl(request.getRequestURL().toString());
					logger.info(request.getRequestURL().toString() + " status:" + response.getStatus());
				}
				dblog.setMethod(request.getMethod());
				dblog.setModuleName(request.getRequestURI());
				dblog.setType("001");
				dblog.setSourceId(getIpAddr(request) + ":" + request.getRemotePort());
				dblog.setOperatorId(WebUtil.getCurrentUser());
				dblog.setLvl(1);
				dblog.setStatus(response.getStatus());

				if (null != startTimeThreadLocal.get()) {
					dblog.setStartTime(DateUtil.format(startTimeThreadLocal.get(), "HH:mm:ss.SSS"));
					dblog.setEndTime(DateUtil.format(startTimeThreadLocal.get(), "HH:mm:ss.SSS"));
					dblog.setTake(
							Float.parseFloat(String.valueOf(System.currentTimeMillis() - startTimeThreadLocal.get())));
				}
				dblog.setClassName(handlerMethod.getBean().getClass().toString());
				dblog.setUserAgent(request.getHeader("user-agent"));
				dblog.setContent("REQ Token:" + request.getHeader("X-AuthToken") + " \r\nParameter:"
						+ JSON.toJSONString(request.getParameterMap()));
				dblog.setRemark("");
				dblog.setResponse("");
				dblog.setHeaders("");
				dblog.setLogTime(new Date());

				// 拦截器中logService 没有注入成功时，重新获取；
				if (sysLogService == null) {
					// System.out.println("logService is null !!!");
					BeanFactory factory = WebApplicationContextUtils
							.getRequiredWebApplicationContext(request.getServletContext());

					sysLogService = (ISysLogService) factory.getBean("sysLogService");

				}

				sysLogService.save(dblog);
			}
		} catch (Exception e) {
			logger.error("用户操作日志记录异常", e);
		}
	}

	// 获取客户端IP
	private String getIpAddr(HttpServletRequest request) {
		String ip = request.getHeader("x-forwarded-for");
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
			ip = request.getRemoteAddr();
		}
		return ip;
	}
}